﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace sinetd.Services.FileTransfer
{
    public class Service : BaseService, IService
    {
        public Service()
            : base("FileTransfer")
        {
            
        }

        public override void ConfigDefault()
        {
            cfg.SetDefault("rootPath", "c:/tmp/data/");
            base.ConfigDefault();

            Directory.CreateDirectory(cfg.GetString("rootPath"));
        }

        private ConnectionPoll connectionPool;

        public void HandleNewConnection(IConnectionIO conn)
        {
            if (connectionPool == null) connectionPool = new ConnectionPoll();

            connectionPool.NewConnection(conn);

            if (!connectionPool.IsRunning)
            {
                connectionPool.Handle += new ConnectionPoll.HandleHandler(connectionPool_Handle);
                connectionPool.Start();
            }
        }

        private void connectionPool_Handle(IConnectionIO iConnectionIO, object p)
        {
            try
            {
                string ans = string.Empty;
                string[] msg = iConnectionIO.Recv().Split(' ');
                switch (msg[0])
                {
                    case "ls":
                        List<string> l = new List<string>();
                        Directory.GetFiles(cfg.GetString("rootPath")).ToList().ForEach(t => l.Add(Path.GetFileName(t)));
                        ans = string.Join(";", l);
                        break;

                    case "put":
                        using (FileStream fs = File.OpenWrite(cfg.GetString("rootPath") + msg[2]))
                        {
                            while (msg[1] != "end")
                            {
                                msg = iConnectionIO.Recv().Split(' ');
                                fs.Write(Convert.FromBase64String(msg[1]), 0, 100);
                            }
                        }
                        break;

                    case "get":
                        foreach (string li in (IEnumerable<string>)put(cfg.GetString("rootPath") + msg[1]))
                        {
                            iConnectionIO.Send(li);
                        }
                        return;
                        break;
                }
                iConnectionIO.Send(ans);
            }
            catch { /* i know */ }
        }

        public void Shutdown()
        {
            if (connectionPool != null)
                if (connectionPool.IsRunning) connectionPool.Stop();
        }

        public string ls()
        {
            return "ls";
        }

        public IEnumerable<string> put(string fileName)
        {
            yield return "put start " + Path.GetFileName(fileName);
            int count = 100;
            byte[] arr = new byte[count];
            using (FileStream fs = File.OpenRead(fileName))
            {
                long fsSize = fs.Length;
                int i = -1;
                while ((fsSize - count) > 0)
                {
                    i++;
                    fs.Read(arr, 0, count);
                    fsSize -= count;
                    yield return "put " + Convert.ToBase64String(arr);
                }

                fs.Read(arr, 0, (int)fsSize);
                yield return "put " + Convert.ToBase64String(arr);
            }
            yield return "put end";
        }

        public string get(string fileName)
        {
            return "get " + fileName;
        }
    }
}
